/**************************************************************************
 *
 * Copyright 2014 MaeckySoft Ltd., Bludenz, Austria.
 * All Rights Reserved.
 *
 **************************************************************************/


#include "MConfigManager.h"
#include "MTools.h"
#include <fstream>
#include <iostream>
#include <string>
#include <algorithm>
#include <cstddef>

#define MAXFILENAMELEN 32
#define MAXFILESIZE 65636

/* TODO: parser needs to be reworked, # sign terminates string reading
         all values needs to be between " signs
*/

char* config_options[] = {
    T("font_file"),
    T("font_size"),
    T("debug_mode"),
    T("char_set"),
    T('\0')
};

int config_options_size;

MConfigManager::MConfigManager(int iDebug, std::string sFilename) : M3DBase(iDebug)
{
	if (iDebug >= MDBG_VERBOSE) std::cout << "(" << __FILE__ << ") <DBG_VERBOSE> " << __PRETTY_FUNCTION__ << " called." << std::endl;
    config_options_size = 0;
    while (config_options[config_options_size] !='\0')
    {
        config_options_size++;
    }

	m_sFilename = "";

	if (sFilename == "") return;

	if (setFileName(sFilename)!=0)
	{
		std::cerr << "(" << __FILE__ << ") <Error> Unable to set name for config file." << std::endl;
	}
    //ctor
}

std::string MConfigManager::getFileName()
{
	if (m_iDebug >= MDBG_ALL) this->printMethodInfo(__PRETTY_FUNCTION__);
	return m_sFilename;
}

void MConfigManager::printMethodInfo(std::string method)
{
	if (m_iDebug == MDBG_ALL) std::cout << "(" << __FILE__ << ") <DBG_ALL> " << method << " called." << std::endl;
}

int MConfigManager::setFileName(std::string sFilename)
{
	if (m_iDebug >= MDBG_ALL) this->printMethodInfo(__PRETTY_FUNCTION__);

	m_sFilename = "";

		if (sFilename.length() > MAXFILENAMELEN){
			std::cerr << "(" << __FILE__ << ") <Error> config filename too long, max. " << MAXFILENAMELEN << " allowed." << std::endl;
			return 1;
		}
		m_sFilename = sFilename;

	return 0;
}


std::string MConfigManager::getValue(char *skey)
{
	if (m_iDebug >= MDBG_ALL) this->printMethodInfo(__PRETTY_FUNCTION__);
        std::string s_key (skey);
        return getValue(s_key);
}

std::string MConfigManager::getValue(std::string skey)
{
	if (m_iDebug >= MDBG_ALL) this->printMethodInfo(__PRETTY_FUNCTION__);

    std::string ret("");
    std::map<std::string, std::string>::iterator tmp = map_config.find(skey);
    if (tmp != map_config.end())
    {
        ret = tmp->second;
    }
    return ret;
}
int MConfigManager::loadConfig()
{
	if (m_iDebug >= MDBG_ALL) this->printMethodInfo(__PRETTY_FUNCTION__);
	if (m_sFilename == "") return 1;
	map_config.clear();
	int linec = 0;
    int bNoerr=true;

	char *zeile=(char*) malloc (sizeof(char) * 65000);

	ifstream datei(m_sFilename.c_str(), ios_base::in);
	if (!datei)
	{
		cerr << "unable to open\n";
	}

	while (datei.getline(zeile, 65000,'\n') && bNoerr)
	{
		linec++;
        bNoerr = parseConfig(zeile);
	};
	if (!bNoerr)
	{
		std::cerr << "(" << __FILE__ << ")  <Error> error parsing config file at line " << linec << "." << std::endl;
	}

    free(zeile);
    if (bNoerr) return 1;
	return 0;
}

bool MConfigManager::parseConfig(char *s){
	if (m_iDebug >= MDBG_ALL) this->printMethodInfo(__PRETTY_FUNCTION__);

    std::string line = s;

    // remove all space characters like \v,' ',\n,\t ...
    line.erase( std::remove_if( line.begin(), line.end(), ::isspace ), line.end() );

    size_t posEqual = line.find_first_of("=");
    size_t posHash = line.find_first_of("#");

    // no euqal sign found -> ignore invalid config line
    string::iterator it = line.begin();
    if (posHash != std::string::npos)
    {
        std::advance(it, posHash);
        line.erase(it, line.end());
    }


    if (posEqual == std::string::npos) return true;
    // found hash sign ?
    if (posHash != std::string::npos)
    {
        // hash sign before equal sign -> comment or invalid config line
        if (posEqual > posHash) return true;
    }


	size_t pos_cfg;
	size_t pos_equal;
	string pvalue;

    for (int i=0; i< config_options_size; i++)
    {

		pos_cfg = line.find(config_options[i]);

		if (pos_cfg != std::string::npos)
		{
			pos_equal = line.find_first_of("=");
			pvalue = line.substr(pos_equal + 1, std::string::npos);

			string cKey (config_options[i]);
			string cValue (pvalue);
			map_config.insert(std::pair<std::string, std::string>(cKey, cValue));
		}
    }
    return true;
}

MConfigManager::~MConfigManager()
{
	if (m_iDebug >= MDBG_VERBOSE) std::cout << "(" << __FILE__ << ") <DBG_VERBOSE> " << __PRETTY_FUNCTION__ << " called." << std::endl;
    //dtor
}

